package dtu.k12tpm.pbs.activity;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import dtu.k12tpm.pbs.contact.ClientContact;
import dtu.k12tpm.pbs.contact.Contact;
import dtu.k12tpm.pbs.service.WebService;
import dtu.k12tpm.pbs.util.ContactProvider;
import dtu.k12tpm.pbs.util.DateFormat;
import dtu.k12tpm.pbs.util.MyXStream;

@SuppressWarnings("deprecation")
public class MainContactListActivity extends MyActivity implements View.OnCreateContextMenuListener, OnItemClickListener {

	private int							numberOfItemSelected = 0;
	private int							item_position_long_clicked;
	private ArrayList<ClientContact>	items;
	private ListView					lv;
	private ArrayAdapter<ClientContact>	aa;
	ContactProvider						cp;
	Handler								myHandler = new Handler();
	TextView view;

	/**
	 * Ham nay dat lai gia tri cho bien: numberOfItemSelected Bien nay nham muc
	 * dich dem so item da select de set label cho menu item Select All truong
	 * hop numberOfItemSelected = so luong hien co thi set label la "Select All"
	 * nguoc lai thi set la "Unselect All"
	 */
	private void countItemChecked() {
		numberOfItemSelected = 0;
		for (int i = 0; i < items.size(); i++) {
			if (items.get(i).isChecked()) {
				numberOfItemSelected++;
			}
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setTitle("Phone Book");
		setContentView(R.layout.contact_list);
		lv = (ListView) findViewById(R.id.List);
		view = (TextView)findViewById(R.id.tvMessageEmptyList);
		try {
			cp = new ContactProvider();
			cp.setCr(getContentResolver());
			cp.setCur(getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, "display_name ASC"));

			items = cp.readBaseContactInfo();
			// sections = cp.readBaseContactInfo0();
			if (items.isEmpty()) {
				((TextView) findViewById(R.id.tvMessageEmptyList)).setText(R.string.msg_EmptyListContact);
			} else {
				((TextView) findViewById(R.id.tvMessageEmptyList)).setText("");
			}
			countItemChecked();

			aa = new ArrayAdapter<ClientContact>(this, R.layout.item_contact_info, items) {
				@Override
				public View getView(int position, View v, ViewGroup parent) {
					if (v == null) {
						LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
						v = vi.inflate(R.layout.item_contact_info, null);
					}
					ClientContact contact = items.get(position);
					if (contact != null) {
						TextView tvTopLeftInfo = (TextView) v.findViewById(R.id.tvTopLeftInfo);
						TextView tvTopRightInfo = (TextView) v.findViewById(R.id.tvTopRightInfo);
						TextView tvBottomRightInfo = (TextView) v.findViewById(R.id.tvBottomRightInfo);
						TextView tvBottomLeftInfo = (TextView) v.findViewById(R.id.tvBottomLeftInfo);

						ImageView iv = (ImageView) v.findViewById(R.id.ImageContact);
						iv.setImageBitmap(contact.getBitmap());
						CheckBox chkSelectContact = (CheckBox) v.findViewById(R.id.chkSelectContact);

						chkSelectContact.setChecked(contact.isChecked());

						HashMap<String, String> info = cp.getContactInfoToShow(contact);
						tvTopLeftInfo.setText(contact.getDisplayName());
						tvTopLeftInfo.setText(contact.getFirstName(info.get("DisplayName")));
						tvTopRightInfo.setText(contact.getLastName(info.get("DisplayName")));
						tvBottomRightInfo.setText(info.get("BottomRightInfo"));
						tvBottomLeftInfo.setText(info.get("BottomLeftInfo"));
					}
					return v;
				}
			};
			lv.setOnCreateContextMenuListener(this);
			lv.setOnItemClickListener(this);
			lv.setAdapter(aa);
		} catch (Exception e) {
			e.printStackTrace();
			showErrorDialog("Code Line 268, " + e.getMessage()).show();
		}
		new AlertNewContact().start();
	}

	private static int	newContactCountOnStart;

	class AlertNewContact extends Thread {
		public void run() {
			while (!isFinishing()) {
				try {
					Thread.sleep(3000);
					final int count = WebService.getNewContactCount(LoginActivity.getUsername());
					if (count > newContactCountOnStart) {
						newContactCountOnStart = count;
						myHandler.post(new Runnable() {
							@Override
							public void run() {
								showMessageDialog("New Contact", "Have " + count + " friend sent contact for you", "View", "Cancel", new OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog, int which) {
										Intent intent = new Intent(MainContactListActivity.this, SenderContactListActivity.class);
										startActivity(intent);
									}
								}, new OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog, int which) {
										dialog.dismiss();
									}
								});
							}
						});
					}

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			Log.i("Thread tracking", "Thread request new contact finished");
		}
	}

	public void onItemClick(AdapterView<?> arg0, View v, int pos, long arg3) {
		try {
			// id_forecast = Integer.parseInt(items.get(pos).getId());
			// maxID = getMaxID();
			Intent i = new Intent();
			i.setAction(Intent.ACTION_VIEW);
			i.setData(Uri.withAppendedPath(android.provider.Contacts.People.CONTENT_URI, "" + items.get(pos).getId()));
			startActivity(i);
		} catch (Exception e) {
			new AlertDialog.Builder(MainContactListActivity.this).setMessage(e.getMessage()).show();
		}
	}

	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
		AdapterView.AdapterContextMenuInfo info;
		try {
			info = (AdapterView.AdapterContextMenuInfo) menuInfo;
		} catch (ClassCastException e) {
			return;
		}

		menu.setHeaderTitle(items.get(item_position_long_clicked = info.position).getDisplayName());
		new MenuInflater(getApplication()).inflate(R.menu.context_menu, menu);
	}

	public static Contact	contactSelected;

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case R.id.select: {
				items.get(item_position_long_clicked).setChecked(!items.get(item_position_long_clicked).isChecked());
				numberOfItemSelected += items.get(item_position_long_clicked).isChecked() ? 1 : -1;
				aa.notifyDataSetChanged();
				break;
			}
			case R.id.delete: {
				showConfirmDialog("Confirm delete", "Are you sure you want to delete?", new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						if (cp.deleteContactWithID(items.get(item_position_long_clicked).getId()) == 0) {
							if (cp.deleteContactWithName(items.get(item_position_long_clicked).getDisplayName()) == 0) {
								showToast("Sorry");
							} else {
								items.remove(item_position_long_clicked);
								numberOfItemSelected--;
								aa.notifyDataSetChanged();
							}
						} else {
							items.remove(item_position_long_clicked);
							numberOfItemSelected--;
							aa.notifyDataSetChanged();
						}
					}
				});
				break;
			}
			case R.id.edit: {
				Intent i = new Intent();
				i.setAction(Intent.ACTION_EDIT);
				i.setData(Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, "" + items.get(item_position_long_clicked).getId()));
				startActivity(i);
				break;
			}
		}
		return true;
	}

	/**
	 * When have just add contact or update contact and revert this screen then
	 * list contact cannot auto refresh even you read again all of contact and
	 * use method notifyDataSetChanged(). Unless you recall method onCreate So,
	 * this problem need optimization. Solution for this problem is se...
	 */


	@Override
	protected void onRestart() {
		// Need get contact's id have just update or add
		onCreate(getIntent().getExtras());
		super.onRestart();
	}

	public void contactCheckButtonClick(View v) {
		CheckBox chk = (CheckBox) v;
		int pos = lv.getPositionForView(v);
		Contact myContact = aa.getItem(pos);
		myContact.setChecked(chk.isChecked());
		numberOfItemSelected += chk.isChecked() ? 1 : -1;
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		new MenuInflater(getApplication()).inflate(R.menu.options_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onMenuOpened(int featureId, Menu menu) {
		if (numberOfItemSelected == items.size()) {
			menu.findItem(R.id.select_all).setTitle(R.string.option_menu_item_UnselectAll);
		} else {
			menu.findItem(R.id.select_all).setTitle(R.string.option_menu_item_SelectAll);
		}
		return super.onMenuOpened(featureId, menu);
	}

	public static String getContactsName() {
		return contacts_name;
	};

	public static String getContactsId() {
		return contacts_id;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			// Options menu
			case R.id.new_contact: {
				Log.i("items size", "" + items.size());
				// maxID = getMaxID();
				// id_forecast = maxID + 1;
				Intent i = new Intent();
				i.setAction(Intent.ACTION_INSERT);
				i.setData(ContactsContract.Contacts.CONTENT_URI);
				startActivity(i);
				break;
			}
			case R.id.delete: {
				if (items.isEmpty()) {
					showToast(R.string.msg_EmptyListContact);
				} else {
					boolean hasCheck = false;
					for (Contact contact : items) {
						if (contact.isChecked()) {
							hasCheck = true;
							break;
						}
					}
					if (hasCheck) {
						// get positions checked
						showConfirmDialog("Confirm Delete", "Are you sure you want to delete?", new OnClickListener() {
							public void onClick(DialogInterface dialog, int which) {
								final ProgressDialog pd = showProgressDialog("Deleting...", false);
								new Thread() {
									public void run() {
										int count = 0;
										for (int i = 0; i < items.size(); i++) {
											Contact myContact = items.get(i);
											if (myContact.isChecked()) {
												if (count < (count += cp.deleteContactWithID(myContact.getId()))) {
													items.remove(myContact);
													numberOfItemSelected--;
													i--;
												} else {
													if (count < (count += cp.deleteContactWithName(myContact.getDisplayName()))) {
														items.remove(myContact);
														numberOfItemSelected--;
														i--;
													}
												}
												myHandler.post(new Thread(){
													public void run(){
														pd.setMessage("Remaining "+ numberOfItemSelected +" contact(s)");
													}
												});
											}
										}
										
										myHandler.post(new Thread(){
											public void run(){
												if (items.isEmpty()) {
													((TextView) findViewById(R.id.tvMessageEmptyList)).setText(R.string.msg_EmptyListContact);
												} else {
													((TextView) findViewById(R.id.tvMessageEmptyList)).setText("");
												}
												aa.notifyDataSetChanged();
												pd.dismiss();
											}
										});										
									}
								}.start();

							}
						});
					} else {
						showToast(R.string.msg_WhenDontSelectContact);
					}
				}

				break;
			}

			case R.id.backup: {
				if (items.isEmpty()) {
					showToast(R.string.msg_EmptyListContact);
				} else {
					showBackupDialog();
				}
				break;
			}
			case R.id.restore: {
				startActivity(RestoreContactActivity.class);
				break;
			}
			case R.id.friend_manager: {
				startActivity(FriendListActivity.class);
				break;
			}
			case R.id.import_sim: {

				break;
			}

			case R.id.export_sd_card: {
				if (items.isEmpty()) {
					showToast(R.string.msg_EmptyListContact);
				} else {
					if (numberOfItemSelected == 0) {
						showToast(R.string.msg_WhenDontSelectContact);
					} else {
						File root = Environment.getExternalStorageDirectory();
						if (root.canWrite()) {
							final File gpxfile = new File(root, "export.xml");
							if (gpxfile.exists()) {
								showConfirmDialog("Confirm File Replace", "Would you like to replace the existing file?", new OnClickListener() {
									@Override
									public void onClick(DialogInterface dialog, int which) {
										ArrayList<Contact> contactsToShare = new ArrayList<Contact>();
										for (ClientContact contact : items) {
											if (contact.isChecked()) {
												contactsToShare.add(cp.readContact(contact.getId()));
											}
										}
//										ArrayList<Contact> contactme = new ArrayList<Contact>();
										
										String t = MyXStream.toXML(contactsToShare);
//										contactme = MyXStream.fromXML(t);
										view.setText("contact to list is: "+ t);
//										exportContactToSDCard(contactsToShare, gpxfile);
										//
										System.out.println("contact to list is: "+t);
//										System.out.println("list to contact  is: "+MyXStream.toXML(contactme));
									}
								});
							} else {
								ArrayList<Contact> contactsToShare = new ArrayList<Contact>();
								for (ClientContact contact : items) {
									if (contact.isChecked()) {
										contactsToShare.add(cp.readContact(contact.getId()));
									}
								}
								exportContactToSDCard(contactsToShare, gpxfile);
							}
						} else {
							showToast("Cannot write on SDCard");
						}
					}
				}
				break;
			}

			case R.id.import_sd_card: {
				File root = Environment.getExternalStorageDirectory();
				if (root.canRead()) {
					if (new File(root, "export.xml").exists()) {
						startActivity(ImportContactFromSDCardActivity.class);
					} else {
						showToast("Cannot found file export.xml on SDCard");
					}
				} else {
					showToast("Cannot read. Permission is limited");
				}

				break;
			}

			case R.id.send: {
				try {
					if (items.isEmpty()) {
						showToast(R.string.msg_EmptyListContact);
					} else {
						if (numberOfItemSelected == 0) {
							showToast(R.string.msg_WhenDontSelectContact);
						} else {
							String[] ids = new String[numberOfItemSelected];
							int i = 0;
							for (Contact contact : items) {
								if (contact.isChecked()) {
									ids[i++] = contact.getId();
								}
							}
							Intent intent = new Intent(this, SendContactActivity.class);
							intent.putExtra("ArrayId", ids);
							contactSelected = null;
							startActivity(intent);
						}
					}
				} catch (Exception e) {
					new AlertDialog.Builder(MainContactListActivity.this).setMessage("Error backupcontact " + e.getMessage()).show();
				}

				break;
			}

			case R.id.receive: {
				startActivity(SenderContactListActivity.class);
				break;
			}
			case R.id.search: {
				onSearchRequested();
				break;
			}
			case R.id.select_all: {
				if (numberOfItemSelected == items.size()) {
					// Unselect all
					for (Contact contact : items) {
						contact.setChecked(false);
					}
					numberOfItemSelected = 0;
				} else {
					// select all
					for (Contact contact : items) {
						contact.setChecked(true);
					}
					numberOfItemSelected = items.size();
				}
				aa.notifyDataSetChanged();
				break;
			}
			case R.id.change_password: {
				changePassword();
				break;
			}
		}
		return super.onOptionsItemSelected(item);
	}

	private void exportContactToSDCard(final ArrayList<Contact> contactsToShare, final File gpxfile) {
		try {
			FileWriter fileWriter = new FileWriter(gpxfile);
			BufferedWriter bffout = new BufferedWriter(fileWriter);
			String xml_content = MyXStream.toXML(contactsToShare);
//			fileWriter.write(xml_content);
//			fileWriter.flush();
//			fileWriter.close();
			bffout.write(xml_content);
			bffout.flush();
			bffout.close();
			new AlertDialog.Builder(MainContactListActivity.this).setMessage("The contacts shared to file export.xml").setTitle("Export success!").setPositiveButton("OK", new OnClickListener() {

				public void onClick(DialogInterface dialog, int which) {
					for (Contact contact : items) {
						contact.setChecked(false);
					}
					aa.notifyDataSetChanged();
				}
			}).show();
		} catch (IOException e) {
			showMessageDialog("IOException", "error while attemping to write file on SDCard");
		}
	}

	private void changePassword() {
		LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View content = vi.inflate(R.layout.change_password, null);
		
		
		final EditText inputBoxOldPassword = (EditText)content.findViewById(R.id.txtOldPassword);
		final EditText inputBoxNewPassword = (EditText)content.findViewById(R.id.txtNewPassword);
		final EditText inputBoxConfirm = (EditText)content.findViewById(R.id.txtConfirmPassword);

		new AlertDialog.Builder(this).setView(content).setTitle("New Password").setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				String old_password = inputBoxOldPassword.getText().toString();
				final String new_password = inputBoxNewPassword.getText().toString();
				String confirm_password = inputBoxConfirm.getText().toString();
				if (new_password.equals("") || confirm_password.equals("")) {
					showMessageDialog(null, "password isn't empty");
				} else {
					if (!LoginActivity.getPassword().equals(old_password))
						showToast("Old password incorrect");
					else {
						if (!new_password.equals(confirm_password))
							showToast("Password confirm incorrect");
						else {
							final ProgressDialog pd = showProgressDialog("Please waiting...", false);
							new Thread(new Runnable() {

								@Override
								public void run() {
									try {
										if (WebService.changePassword(LoginActivity.getUsername(), new_password)) {
											myHandler.post(new Runnable() {
												public void run() {
													showToast("Your password changed");
												}
											});
										} else {
											myHandler.post(new Runnable() {
												public void run() {
													showToast("Have an error when attempting to change password!");
												}
											});
										}
										myHandler.post(new Runnable() {
											public void run() {
												pd.dismiss();
											}
										});
									} catch (final Exception e) {
										myHandler.post(new Runnable() {
											public void run() {
												pd.dismiss();
												showErrorDialog("System: " + e.getMessage());
											}
										});
									}
								}
							}).start();
						}

					}
				}
			}
		}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				d.dismiss();
			}
		}).create().show();
	}

	public void showBackupDialog() {
		final LinearLayout ll = new LinearLayout(this);
		final EditText inputBoxNotes = new EditText(this, null);

		ll.setOrientation(LinearLayout.VERTICAL);
		ll.setPadding(5, 5, 5, 5);
		ll.addView(inputBoxNotes, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
		inputBoxNotes.setHint("Notes");
		new AlertDialog.Builder(this).setView(ll).setIcon(R.drawable.backup_icon).setTitle("Backup Contact").setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				final ProgressDialog pd = showProgressDialog(null, "Please waiting", false);
				new Thread() {
					public void run() {
						String notes = inputBoxNotes.getText().toString();
						try {
							if (WebService.backupContactList(cp.readFullContactInfo(), LoginActivity.getUserID(), notes, getDate(DateFormat.DDMMYYYY, "-"), getTime())) {
								myHandler.post(new Runnable() {
									public void run() {
										showToast("Backup completed");
									}
								});
							} else {
								myHandler.post(new Runnable() {
									public void run() {
										showToast("Backup error!");
									}
								});
							}
						} catch (final Exception e) {
							myHandler.post(new Runnable() {
								public void run() {
									showErrorDialog("Please check again connection." + e.getMessage());
								}
							});
						}
						pd.dismiss();
					}
				}.start();
			}
		}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				d.dismiss();
			}
		}).create().show();
	}

	private static String	contacts_name	= "";
	private static String	contacts_id		= "";
}
